home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / tests / psh / psh.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-10  |  10.7 KB  |  488 lines

  1. /* 
  2.  * psh.c --
  3.  *
  4.  *    Really primitive shell.  Reads and executes commands in a loop 
  5.  *    until it gets end-of-file.
  6.  *
  7.  * Copyright 1991 Regents of the University of California
  8.  * Permission to use, copy, modify, and distribute this
  9.  * software and its documentation for any purpose and without
  10.  * fee is hereby granted, provided that this copyright
  11.  * notice appears in all copies.  The University of California
  12.  * makes no representations about the suitability of this
  13.  * software for any purpose.  It is provided "as is" without
  14.  * express or implied warranty.
  15.  */
  16.  
  17. #ifndef lint
  18. static char rcsid[] = "$Header: /user5/kupfer/spriteserver/tests/psh/RCS/psh.c,v 1.8 92/06/10 14:10:28 kupfer Exp $ SPRITE (Berkeley)";
  19. #endif /* not lint */
  20.  
  21. #include <sprite.h>
  22. #include <bstring.h>
  23. #include <ctype.h>
  24. #include <errno.h>
  25. #include <fs.h>
  26. #include <rpc.h>
  27. #include <spriteTime.h>
  28. #include <status.h>
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <string.h>
  32. #include <sys.h>
  33. #include <sys/wait.h>
  34. #include <sys/time.h>
  35. #include <sys/resource.h>
  36. #include <sysStats.h>
  37. #include <test.h>
  38. #include <unistd.h>
  39.  
  40. #include <testRedef.h>
  41.  
  42. #define CMD_BUF_SIZE    4096
  43. #define MAX_ARGS    110
  44.  
  45. #define BIN_DIR    "/users/kupfer/cmds.sprited/" /* standard directory for 
  46.                            * commands */
  47.  
  48. /* forward declarations: */
  49.  
  50. static void Cd _ARGS_((char *command));
  51. static void DoCmd _ARGS_((char *command));
  52. static void DoExec _ARGS_((char *command));
  53. static ReturnStatus DoTest _ARGS_((int command, int serverID,
  54.                    int numEchoes, int size, 
  55.                    Address inDataBuffer,
  56.                    Address outDataBuffer, Time *timePtr));
  57. static void MakeArgArray _ARGS_((char *command, char **argArray));
  58. static void Ping _ARGS_((char *command));
  59. static void RpcCmd _ARGS_((char *command));
  60.  
  61.  
  62. /*
  63.  *----------------------------------------------------------------------
  64.  *
  65.  * main --
  66.  *
  67.  *    Command loop.
  68.  *
  69.  * Results:
  70.  *    None.
  71.  *
  72.  * Side effects:
  73.  *    None.
  74.  *
  75.  *----------------------------------------------------------------------
  76.  */
  77.     
  78. void
  79. main()
  80. {
  81.     char command[CMD_BUF_SIZE];
  82.  
  83.     for (;;) {
  84.     Test_PutMessage("> ");
  85.     Test_GetString(command, CMD_BUF_SIZE);
  86.     if (command[0] == '\0') {
  87.         break;
  88.     }
  89.     DoCmd(command);
  90.     }
  91.  
  92.     exit(0);
  93. }
  94.  
  95.  
  96. /*
  97.  *----------------------------------------------------------------------
  98.  *
  99.  * DoCmd --
  100.  *
  101.  *    Execute a command.  For most commands, this means: fork off a 
  102.  *    child, exec the named program, and wait for it to finish.  A couple 
  103.  *    commands are built-ins.
  104.  *
  105.  * Results:
  106.  *    None.
  107.  *
  108.  * Side effects:
  109.  *    None.
  110.  *
  111.  *----------------------------------------------------------------------
  112.  */
  113.  
  114. static void
  115. DoCmd(command)
  116.     char *command;        /* the command to execute */
  117. {
  118.     Boolean waitForChild = TRUE; /* wait for child to exit */
  119.     pid_t child;
  120.  
  121.     /* 
  122.      * Get rid of the trailing newline.
  123.      */
  124.     if (command[strlen(command)-1] == '\n') {
  125.     command[strlen(command)-1] = '\0';
  126.     }
  127.  
  128.     if (strcmp(command, "memcheck") == 0) {
  129.     Test_MemCheck("dummyFile");
  130.     return;
  131.     } else if (strncmp(command, "RpcCmd", strlen("RpcCmd")) == 0) {
  132.     RpcCmd(command);
  133.     return;
  134.     } else if (strncmp(command, "Ping", strlen("Ping")) == 0) {
  135.     Ping(command);
  136.     return;
  137.     } else if (strncmp(command, "cd", strlen("cd")) == 0) {
  138.     Cd(command);
  139.     return;
  140.     } else if (strncmp(command, "shutdown", strlen("shutdown")) == 0) {
  141.     (void)Sys_Shutdown(SYS_HALT|SYS_KILL_PROCESSES|SYS_WRITE_BACK,
  142.                NULL);
  143.     return;
  144.     } else if (strncmp(command, "bg", strlen("bg")) == 0) {
  145.     /* "background" command */
  146.     command += strlen("bg");
  147.     waitForChild = FALSE;
  148.     }
  149.  
  150.     child = fork();
  151.     switch (child) {
  152.     case -1:
  153.     perror("Fork failed");
  154.     break;
  155.     case 0:
  156.     /* child */
  157.     DoExec(command);
  158.     exit(1);
  159.     break;
  160.     default:
  161.     /* 
  162.      * Parent.  If it's a synchronous command, wait for the current 
  163.      * child and reap any previous, exited children.  If it's a
  164.      * background command, just give the process ID of the child.
  165.      */
  166.     if (waitForChild) {
  167.         while (wait((union wait *)0) != child) {
  168.         ;
  169.         }
  170.         while (wait3((union wait *)0, WNOHANG, (struct rusage *)0) > 0) {
  171.         ;
  172.         }
  173.     } else {
  174.         Test_PutMessage("[");
  175.         Test_PutHex(child);
  176.         Test_PutMessage("]\n");
  177.     }
  178.     break;
  179.     }
  180. }
  181.  
  182.  
  183. /*
  184.  *----------------------------------------------------------------------
  185.  *
  186.  * DoExec --
  187.  *
  188.  *    Get the program name and arguments from the command string and exec 
  189.  *    the right program.
  190.  *
  191.  * Results:
  192.  *    None.  Returns only if there's an error.
  193.  *
  194.  * Side effects:
  195.  *    None.
  196.  *
  197.  *----------------------------------------------------------------------
  198.  */
  199.  
  200. static void
  201. DoExec(command)
  202.     char *command;        /* the user's command string */
  203. {
  204.     char *args[MAX_ARGS];    /* argument pointers */
  205.     char altCommand[FS_MAX_PATH_NAME_LENGTH];
  206.  
  207.     bzero((_VoidPtr)args, MAX_ARGS);
  208.  
  209.     /* Skip over initial whitespace */
  210.     while (isspace(*command)) {
  211.     command++;
  212.     }
  213.  
  214.     MakeArgArray(command, args);
  215.     if (args[0] == '\0') {
  216.     exit(0);
  217.     }
  218.  
  219.     (void)execv(command, args);
  220.  
  221.     /* 
  222.      * If the exec failed because the file doesn't exist, maybe it's in the 
  223.      * "bin" directory.
  224.      */
  225.     if (errno == ENOENT) {
  226.     (void)strcpy(altCommand, BIN_DIR);
  227.     (void)strcat(altCommand, command);
  228.     (void)execv(altCommand, args);
  229.     }
  230.  
  231.     Test_PutMessage("exec of `");
  232.     Test_PutMessage(command);
  233.     perror("'failed");
  234. }
  235.  
  236.  
  237. /*
  238.  *----------------------------------------------------------------------
  239.  *
  240.  * MakeArgArray --
  241.  *
  242.  *    Break the command line up into argument strings.  
  243.  *    
  244.  * Results:
  245.  *    Fills in the arguments array with pointers into the given command 
  246.  *    string.  The last argument pointer is made nil.
  247.  *
  248.  * Side effects:
  249.  *    Puts null bytes in the command string to end the argument strings.
  250.  *
  251.  *----------------------------------------------------------------------
  252.  */
  253.  
  254. static void
  255. MakeArgArray(command, argArray)
  256.     char *command;        /* command string */
  257.     char **argArray;        /* OUT: argument pointers */
  258. {
  259.     int argNum;
  260.     char *chPtr;
  261.  
  262.     /* 
  263.      *    The command string is a bunch of words separated by whitespace.  
  264.      *    Each of these words is turned into a separate argument string by 
  265.      *    sticking a null at the first whitespace character.
  266.      */
  267.  
  268.     /* Skip over initial whitespace */
  269.     chPtr = command;
  270.     while (isspace(*chPtr)) {
  271.     chPtr++;
  272.     }
  273.     if (*chPtr == '\0') {
  274.     /* null command */
  275.     argArray[0] = '\0';
  276.     return;
  277.     }
  278.     argArray[0] = chPtr;
  279.     argNum = 1;
  280.  
  281.     for (; *chPtr != '\0'; chPtr++) {
  282.     if (isspace(*chPtr)) {
  283.         *chPtr = '\0';
  284.         ++chPtr;
  285.         /* skip over additional whitespace */
  286.         while (isspace(*chPtr)) {
  287.         chPtr++;
  288.         }
  289.         /* if there's another argument, remember where it starts. */
  290.         if (*chPtr != '\0') {
  291.         argArray[argNum] = chPtr;
  292.         argNum++;
  293.         }
  294.         if (argNum >= MAX_ARGS-1) {
  295.         Test_PutMessage("Too many arguments.\n");
  296.         break;
  297.         }
  298.     }
  299.     }
  300.  
  301.     argArray[argNum] = '\0';
  302. }
  303.  
  304.  
  305. /*
  306.  *----------------------------------------------------------------------
  307.  *
  308.  * RpcCmd --
  309.  *
  310.  *    Built-in to replace rpccmd, at least partially.
  311.  *
  312.  * Results:
  313.  *    None.
  314.  *
  315.  * Side effects:
  316.  *    Issues a Sys_Stats call to the server, depending on arguments 
  317.  *    to the command.
  318.  *
  319.  *----------------------------------------------------------------------
  320.  */
  321.  
  322. static void
  323. RpcCmd(command)
  324.     char *command;        /* the actual user command */
  325. {
  326.     int commandLength;        /* characters in user command */
  327.     char *usage;        /* "usage" string in case of user error */
  328.     ReturnStatus status = SUCCESS;
  329.  
  330.     usage = "usage: RpcCmd [on|off]\n";
  331.     commandLength = strlen(command);
  332.     if (commandLength <= strlen("RpcCmd ")) {
  333.     Test_PutMessage(usage);
  334.     return;
  335.     }
  336.     command += strlen("RpcCmd ");
  337.     if (strcmp(command, "on") == 0) {
  338.     status = Sys_Stats(SYS_RPC_ENABLE_SERVICE, TRUE, (Address)NULL);
  339.     } else if (strcmp(command, "off") == 0) {
  340.     status = Sys_Stats(SYS_RPC_ENABLE_SERVICE, FALSE, (Address)NULL);
  341.     } else {
  342.     Test_PutMessage(usage);
  343.     return;
  344.     }
  345.     if (status != SUCCESS) {
  346.     Test_PutMessage("Couldn't turn RPC's ");
  347.     Test_PutMessage(command);
  348.     Test_PutMessage(": ");
  349.     Test_PutMessage(Stat_GetMsg(status));
  350.     Test_PutMessage("\n");
  351.     }
  352. }
  353.  
  354.  
  355. /*
  356.  *----------------------------------------------------------------------
  357.  *
  358.  * Ping --
  359.  *
  360.  *    Do the RPC ping test to the named host.
  361.  *
  362.  * Results:
  363.  *    None.
  364.  *
  365.  * Side effects:
  366.  *    None.
  367.  *
  368.  *----------------------------------------------------------------------
  369.  */
  370.  
  371. static void
  372. Ping(command)
  373.     char *command;        /* the user's command */
  374. {
  375.     int serverID;        /* server to ping */
  376.     int commandLength;        /* characters in user command */
  377.     char *usage;        /* "usage" string in case of user error */
  378.     ReturnStatus status;
  379.     char buffer[16 * 1024];
  380.     Time deltaTime;
  381.     int    numEchoes = 100;
  382.     int    blockSize = 32;
  383.  
  384.     usage = "usage: Ping host_ID\n";
  385.     commandLength = strlen(command);
  386.     if (commandLength <= strlen("Ping ")) {
  387.     Test_PutMessage(usage);
  388.     return;
  389.     }
  390.     command += strlen("Ping ");
  391.     serverID = atoi(command);
  392.     Test_PutMessage("Pinging server ");
  393.     Test_PutDecimal(serverID);
  394.     Test_PutMessage("\n");
  395.  
  396.     status = DoTest(TEST_RPC_SEND, serverID, numEchoes, blockSize, buffer,
  397.             buffer, &deltaTime);
  398.     if (status != SUCCESS) {
  399.     Test_PutMessage("RPC failed: ");
  400.     Test_PutMessage(Stat_GetMsg(status));
  401.     Test_PutMessage("\n");
  402.     } else {
  403.     Test_PutMessage("Send ");
  404.     Test_PutDecimal(blockSize);
  405.     Test_PutMessage(" bytes ");
  406.     Test_PutDecimal(deltaTime.seconds);
  407.     Test_PutMessage(" seconds, ");
  408.     Test_PutDecimal(deltaTime.microseconds);
  409.     Test_PutMessage(" microseconds.\n");
  410.     }
  411. }
  412.  
  413.  
  414. /*
  415.  *----------------------------------------------------------------------
  416.  *
  417.  * DoTest --
  418.  *
  419.  *    Actually do the RPC ping test.
  420.  *
  421.  * Results:
  422.  *    None.
  423.  *
  424.  * Side effects:
  425.  *    None.
  426.  *
  427.  *----------------------------------------------------------------------
  428.  */
  429.  
  430. static ReturnStatus
  431. DoTest(command, serverID, numEchoes, size, inDataBuffer, outDataBuffer, 
  432.        timePtr)
  433.     int command;
  434.     int serverID;
  435.     int numEchoes;
  436.     int size;
  437.     Address inDataBuffer;
  438.     Address outDataBuffer;
  439.     Time *timePtr;
  440. {
  441.     Rpc_EchoArgs echoArgs;
  442.     ReturnStatus error;
  443.  
  444.     echoArgs.serverID = serverID;
  445.     echoArgs.n = numEchoes;
  446.     echoArgs.size = size;
  447.     echoArgs.inDataPtr = inDataBuffer;
  448.     echoArgs.outDataPtr = outDataBuffer;
  449.     echoArgs.deltaTimePtr = timePtr;
  450.     error = Test_Rpc(command, (Address)&echoArgs);
  451.  
  452.     return(error);
  453. }
  454.  
  455.  
  456. /*
  457.  *----------------------------------------------------------------------
  458.  *
  459.  * Cd --
  460.  *
  461.  *    Change the current working directory.
  462.  *
  463.  * Results:
  464.  *    None.
  465.  *
  466.  * Side effects:
  467.  *    None.
  468.  *
  469.  *----------------------------------------------------------------------
  470.  */
  471.  
  472. static void
  473. Cd(command)
  474.     char *command;        /* user's command string */
  475. {
  476.     int commandLength = strlen(command);
  477.  
  478.     if (commandLength <= strlen("cd ")) {
  479.     Test_PutMessage("Usage: cd directory\n");
  480.     return;
  481.     }
  482.  
  483.     command += strlen("cd ");
  484.     if (chdir(command) < 0) {
  485.     perror(command);
  486.     }
  487. }
  488.